home *** CD-ROM | disk | FTP | other *** search
/ io Programmo 60 / IOPROG_60.ISO / soft / c++ / gsl-1.1.1-setup.exe / {app} / src / ieee-utils / make_rep.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-05-05  |  4.5 KB  |  198 lines

  1. /* ieee-utils/make_rep.c
  2.  * 
  3.  * Copyright (C) 1996, 1997, 1998, 1999, 2000 Brian Gough
  4.  * 
  5.  * This program is free software; you can redistribute it and/or modify
  6.  * it under the terms of the GNU General Public License as published by
  7.  * the Free Software Foundation; either version 2 of the License, or (at
  8.  * your option) any later version.
  9.  * 
  10.  * This program is distributed in the hope that it will be useful, but
  11.  * WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  13.  * General Public License for more details.
  14.  * 
  15.  * You should have received a copy of the GNU General Public License
  16.  * along with this program; if not, write to the Free Software
  17.  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18.  */
  19.  
  20. #include <config.h>
  21. #include <gsl/gsl_ieee_utils.h>
  22.  
  23. #include "endian.c"
  24. #include "standardize.c"
  25.  
  26. static void sprint_nybble(int i, char *s) ;
  27. static void sprint_byte(int i, char *s) ;
  28. static int determine_ieee_type (int non_zero, int exponent, int max_exponent);
  29.  
  30.  
  31. /* For the IEEE float format the bits are found from the following
  32.    masks,
  33.    
  34.    sign      = 0x80000000  
  35.    exponent  = 0x7f800000 
  36.    mantisssa = 0x007fffff  
  37.  
  38.    For the IEEE double format the masks are,
  39.  
  40.    sign      = 0x8000000000000000  
  41.    exponent  = 0x7ff0000000000000 
  42.    mantissa  = 0x000fffffffffffff
  43.  
  44.    */
  45.  
  46. void 
  47. gsl_ieee_float_to_rep (const float * x, gsl_ieee_float_rep * r)
  48. {
  49.   int e, non_zero;
  50.  
  51.   union { 
  52.     float f;
  53.     struct  { 
  54.       unsigned char byte[4] ;
  55.     } ieee ;
  56.   } u;
  57.   
  58.   u.f = *x ; 
  59.  
  60.   if (little_endian_p())
  61.     make_float_bigendian(&(u.f)) ;
  62.   
  63.   /* note that r->sign is signed, u.ieee.byte is unsigned */
  64.  
  65.   if (u.ieee.byte[3]>>7)
  66.     {
  67.       r->sign = 1 ;
  68.     }
  69.   else
  70.     {
  71.       r->sign = 0 ;
  72.     }
  73.  
  74.   e = (u.ieee.byte[3] & 0x7f) << 1 | (u.ieee.byte[2] & 0x80)>>7 ; 
  75.   
  76.   r->exponent = e - 127 ;
  77.  
  78.   sprint_byte((u.ieee.byte[2] & 0x7f) << 1,r->mantissa) ;
  79.   sprint_byte(u.ieee.byte[1],r->mantissa + 7) ;
  80.   sprint_byte(u.ieee.byte[0],r->mantissa + 15) ;
  81.  
  82.   r->mantissa[23] = '\0' ;
  83.  
  84.   non_zero = u.ieee.byte[0] || u.ieee.byte[1] || (u.ieee.byte[2] & 0x7f);
  85.  
  86.   r->type = determine_ieee_type (non_zero, e, 255) ;
  87. }
  88.  
  89. void 
  90. gsl_ieee_double_to_rep (const double * x, gsl_ieee_double_rep * r)
  91. {
  92.  
  93.   int e, non_zero;
  94.  
  95.   union 
  96.   { 
  97.     double d;
  98.     struct  { 
  99.       unsigned char byte[8];
  100.     } ieee ;
  101.   } u;
  102.  
  103.   u.d= *x ; 
  104.   
  105.   if (little_endian_p())
  106.     make_double_bigendian(&(u.d)) ;
  107.   
  108.   /* note that r->sign is signed, u.ieee.byte is unsigned */
  109.  
  110.   if (u.ieee.byte[7]>>7)
  111.     {
  112.       r->sign = 1 ;
  113.     }
  114.   else
  115.     {
  116.       r->sign = 0 ;
  117.     }
  118.  
  119.  
  120.   e =(u.ieee.byte[7] & 0x7f)<<4 ^ (u.ieee.byte[6] & 0xf0)>>4 ;
  121.   
  122.   r->exponent = e - 1023 ;
  123.  
  124.   sprint_nybble(u.ieee.byte[6],r->mantissa) ;
  125.   sprint_byte(u.ieee.byte[5],r->mantissa + 4) ;
  126.   sprint_byte(u.ieee.byte[4],r->mantissa + 12) ;
  127.   sprint_byte(u.ieee.byte[3],r->mantissa + 20) ; 
  128.   sprint_byte(u.ieee.byte[2],r->mantissa + 28) ;
  129.   sprint_byte(u.ieee.byte[1],r->mantissa + 36) ;
  130.   sprint_byte(u.ieee.byte[0],r->mantissa + 44) ;
  131.  
  132.   r->mantissa[52] = '\0' ;
  133.  
  134.   non_zero = (u.ieee.byte[0] || u.ieee.byte[1] || u.ieee.byte[2]
  135.           || u.ieee.byte[3] || u.ieee.byte[4] || u.ieee.byte[5] 
  136.           || (u.ieee.byte[6] & 0x0f)) ;
  137.  
  138.   r->type = determine_ieee_type (non_zero, e, 2047) ;
  139. }
  140.  
  141. /* A table of character representations of nybbles */
  142.  
  143. static char nybble[16][5]={ /* include space for the \0 */
  144.   "0000", "0001", "0010", "0011",
  145.   "0100", "0101", "0110", "0111",
  146.   "1000", "1001", "1010", "1011",
  147.   "1100", "1101", "1110", "1111"
  148. }  ;
  149.       
  150. static void
  151. sprint_nybble(int i, char *s)
  152. {
  153.   char *c ;
  154.   c=nybble[i & 0x0f ];
  155.   *s=c[0] ;  *(s+1)=c[1] ;  *(s+2)=c[2] ;  *(s+3)=c[3] ;
  156.  
  157. static void
  158. sprint_byte(int i, char *s)
  159. {
  160.   char *c ;
  161.   c=nybble[(i & 0xf0)>>4];
  162.   *s=c[0] ;  *(s+1)=c[1] ;  *(s+2)=c[2] ;  *(s+3)=c[3] ;
  163.   c=nybble[i & 0x0f];
  164.   *(s+4)=c[0] ;  *(s+5)=c[1] ;  *(s+6)=c[2] ;  *(s+7)=c[3] ;
  165.  
  166. static int 
  167. determine_ieee_type (int non_zero, int exponent, int max_exponent)
  168. {
  169.   if (exponent == max_exponent)
  170.     {
  171.       if (non_zero)
  172.     {
  173.       return GSL_IEEE_TYPE_NAN ;
  174.     }
  175.       else
  176.     {
  177.       return GSL_IEEE_TYPE_INF ;
  178.     }
  179.     }
  180.   else if (exponent == 0)
  181.     {
  182.       if (non_zero)
  183.     {
  184.       return GSL_IEEE_TYPE_DENORMAL ;
  185.     }
  186.       else
  187.     {
  188.       return GSL_IEEE_TYPE_ZERO ;
  189.     }
  190.     }
  191.   else
  192.     {
  193.       return GSL_IEEE_TYPE_NORMAL ;
  194.     }
  195. }
  196.